#import "EventViewer.h"

// The shared instance of EventViewer
static EventViewer* sharedEventViewer = nil;

/**
 * An EventViewer is an object representing the view that 
 * displays information regarding a given SFU event.
 *
 * An EventViewerDelegate must be set to respond to events from
 * within the event viewer.
 *
 * Conforms to UIScrollViewDelegate protocol.
 *
 * @author      James Lin
 * @version     0.7.4
 * @since       0.2.0
 * @see         UIScrollViewDelegate
 * @see         EventViewerDelegate
 */
@implementation EventViewer

@synthesize eventInfo;

/**
 * Retrieve the shared instance of the event viewer.
 *
 * @return  the shared instance of EventViewer
 */
+ (EventViewer*)sharedEventViewer {
	@synchronized(self) {
		if (sharedEventViewer == nil) {
			sharedEventViewer = [[EventViewer alloc] initWithNibName:nil 
															  bundle:nil];
		}
		return sharedEventViewer;
	}
}

/**
 * Allocate the event viewer.
 *
 * @return  the newly allocated shared instance of EventViewer
 */
+ (id) alloc {
	@synchronized(self) {
		sharedEventViewer = [super alloc];
		return sharedEventViewer;
	}
}

/**
 * Retrieve a copy of the event viewer.
 *
 * @return  the shared instance of EventViewer
 */
+ (id) copy {
	@synchronized(self) {
		return sharedEventViewer;
	}
}

/**
 * Get the delegate handling events from the event viewer.
 *
 * @return  the delegate handling events from event view
 * @see     EventViewerDelegate
 */
- (id<EventViewerDelegate>)delegate {
	return delegate;
}

/**
 * Set the delegate handling events from the event viewer.
 *
 * param theDelegate  the delegate handling events from event view
 * @see               EventViewerDelegate
 */
- (void)setDelegate:(id<EventViewerDelegate>)theDelegate {
	delegate = theDelegate;
}

/**
 * Create a UILabel resized to its text content.
 *
 * @param labelContent  the text to place in the label
 * @param font          the font type and size of the text
 * @param textColor     the color of the text
 * @param padding       vertical padding on the top and bottom sides of the label
 * @return              a newly allocated UILabel with the specified text and style
 */
- (UILabel*)getLabelResizedToText:(NSString*)labelContent 
							 font:(UIFont*)font 
						 textColor:(UIColor*)textColor 
						  padding:(CGFloat)padding {
	contentHeight += padding; // Top padding
	
	CGRect labelFrame = CGRectMake(HORIZONTAL_PADDING, contentHeight, 
								   VIEW_WIDTH-HORIZONTAL_PADDING*2, 0);
	UILabel* tempLabel = [[UILabel alloc] initWithFrame:labelFrame];
	
	// Set the label's text and properties
	tempLabel.text = labelContent;
	tempLabel.font = (font == nil) ? [UIFont systemFontOfSize:12.0] : font;
	tempLabel.textColor = (textColor == nil) ? [UIColor blackColor] : textColor;
	tempLabel.backgroundColor = [UIColor clearColor];
	tempLabel.numberOfLines = 0;
	
	// Resize the label to fit text
	CGRect frame = [tempLabel frame];
	CGSize size = [tempLabel.text sizeWithFont:tempLabel.font 
							 constrainedToSize:CGSizeMake(frame.size.width, CGFLOAT_MAX) 
								 lineBreakMode:UILineBreakModeWordWrap];
	
	frame.size.height = size.height;
	contentHeight += size.height + padding; // Label height + bottom padding
	[tempLabel setFrame:frame];
	
	return tempLabel;
}

/**
 * Update the navigation bar.
 */
- (void)updateNavigationBar {
	UIBarButtonItem* rightButton;
	
	if (eventInfo != nil) {
		if (eventInfo.isBookmarked) {
			rightButton = [[UIBarButtonItem alloc] initWithTitle:@"Remove" 
														   style:UIBarButtonItemStyleDone 
														  target:self 
														  action:@selector(deleteEvent)];
		} else {
			rightButton = [[UIBarButtonItem alloc] initWithTitle:@"Bookmark" 
														   style:UIBarButtonItemStyleDone 
														  target:self 
														  action:@selector(bookmarkEvent)];
		}
		[self.navigationItem setRightBarButtonItem:rightButton];
		[rightButton release];
	}
}

/**
 * Display the event information in a new view.
 *
 * Pushes this view onto the navigation controller stack of the parent
 * view. Upon tapping the back button, the view is automatically 
 * popped off the top of the navigation stack.
 *
 * @param event          the event to display
 * @param navController  the navigation controller of the parent view
 */
- (void)displayEvent:(SFUEvent*)event 
	   navController:(UINavigationController*)navController {
	// Reset the event view
	for (UIView* subview in zoomableView.subviews) {
		[subview removeFromSuperview];
	}
	
	// Save the event information
	eventInfo = event;
	contentHeight = 0;
	
	// Set navigation properties
	self.navigationItem.title = @"Event Details";
	[self updateNavigationBar];
	parentNav = navController;
	
	// Create the event's heading label and add to view
	UILabel *headingLabel = [self getLabelResizedToText:eventInfo.eventHeading 
												   font:[UIFont boldSystemFontOfSize:18.0]
											  textColor:nil
												padding:7];
	[zoomableView addSubview:headingLabel];
	[headingLabel release];
	
	// Create the event's category label and add to view
	UILabel *categoryLabel = [self getLabelResizedToText:eventInfo.eventCategory 
													font: [UIFont italicSystemFontOfSize:12] 
											   textColor: [UIColor blackColor] 
												 padding: 0];
	[zoomableView addSubview:categoryLabel];
	[categoryLabel release];
	
	// Create the event's start datetime label and add to view
	NSDateFormatter* dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
	[dateFormatter setDateFormat:@"EEE',' dd MMM yyyy HH:mm ZZZ"];
	UILabel *startDTLabel;
	startDTLabel = [self getLabelResizedToText:[dateFormatter stringFromDate:eventInfo.eventStartDateTime] 
										  font:[UIFont boldSystemFontOfSize:12.0] 
									 textColor:[UIColor darkGrayColor] 
									   padding:2];
	[zoomableView addSubview:startDTLabel];
	[startDTLabel release];
	
	// Create the event's end datetime label and add to view
	UILabel *endDTLabel;
	endDTLabel = [self getLabelResizedToText:[dateFormatter stringFromDate:eventInfo.eventEndDateTime] 
										font:[UIFont boldSystemFontOfSize:12.0] 
								   textColor:[UIColor darkGrayColor] 
									 padding:2];
	[zoomableView addSubview:endDTLabel];
	[endDTLabel release];
	
	// Create the event's location label and add to view
	UILabel* locationLabel = [self getLabelResizedToText:eventInfo.eventLocation 
													font:[UIFont boldSystemFontOfSize:12.0] 
											   textColor:[UIColor blackColor] 
												 padding:3];
	[zoomableView addSubview:locationLabel];
		
	// Create the button to view event location on a map if necessary
	[locationButton setHidden:YES];
	if ([eventInfo.eventLocation length] > 0) {
		// Create the button and set its properties
		locationButton = [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];
		locationButton.frame = CGRectMake(0,0,90,20);
		[locationButton setTitle:@"View on map" forState:UIControlStateNormal];
		locationButton.titleLabel.font = [UIFont boldSystemFontOfSize:13];
		locationButton.titleLabel.textColor = [UIColor colorWithRed:0.67 
															  green:0.08 
															   blue:0.08 
															  alpha:1.0];
		[locationButton setBackgroundColor:[UIColor lightGrayColor]];
		[locationButton addTarget:self 
						   action:@selector(viewOnMap) 
				 forControlEvents:UIControlEventTouchUpInside];
		[zoomableView addSubview:locationButton];
		
		CGSize size = [locationLabel.text sizeWithFont:locationLabel.font 
								 constrainedToSize:CGSizeMake(locationLabel.frame.size.width, 9999) 
									 lineBreakMode:UILineBreakModeWordWrap];
		CGPoint pos;
		pos.x = locationLabel.center.x + size.width/2;
		pos.y = locationLabel.center.y;
		[locationButton setCenter:pos];
		[locationButton setHidden:NO];
	}
	
	[locationLabel release];
	
	// Create the event's contact information label and add to view
	UILabel *contactInfoLabel = [self getLabelResizedToText:eventInfo.eventContactInfo 
													   font: nil 
												  textColor: [UIColor colorWithRed:0.13 
																			 green:0.17 
																			  blue:0.62 
																			 alpha:1.0] 
													padding: 5];
	[zoomableView addSubview:contactInfoLabel];
	[contactInfoLabel release];
	
	// Create the event's description label and add to view
	UILabel *descriptionLabel = [self getLabelResizedToText:eventInfo.eventDescription 
													   font: nil 
												  textColor: nil
													padding: 10];
	[zoomableView addSubview:descriptionLabel];
	[descriptionLabel release];
	
	// Refit the view to the labels
	[zoomableView setFrame:CGRectMake(0, 0, VIEW_WIDTH, contentHeight+50)];
	[eventInfoView setContentSize:CGSizeMake(VIEW_WIDTH, contentHeight+50)];
	
	// Display the event view
	[eventInfoView addSubview:zoomableView];
	[self.view addSubview:eventInfoView];
	[navController pushViewController:self animated:YES];
}

/**
 * Handle a bookmark event request.
 */
- (void)bookmarkEvent {
	if ([delegate eventShouldBookmark:eventInfo]) {
		eventInfo.isBookmarked = YES;
		[self updateNavigationBar];
	}
}

/**
 * Handle a delete bookmarked event request.
 */
- (void)deleteEvent {
	if ([delegate eventShouldDelete:eventInfo]) {
		[parentNav popViewControllerAnimated:YES];
	}
}

/**
 * Request to view the location of the event on a map.
 */
- (void)viewOnMap {
	if ([delegate respondsToSelector:@selector(viewLocationOfEvent:)]) {
		[delegate viewLocationOfEvent:eventInfo];
		[parentNav popViewControllerAnimated:YES];
	}
}
	 
/**
 * Enable support for zooming in the event view.
 */
- (UIView*)viewForZoomingInScrollView:(UIScrollView*)scrollView {
	return zoomableView;
}

/**
 * Handle the single finger double tap gesture.
 *
 * Resets the zoom scale to default.
 */
- (IBAction)handleSingleFingerDoubleTap:(UIGestureRecognizer*)sender {
	[eventInfoView setZoomScale:1.0 animated:YES];
}

/**
 * Reset the view prior to it appearing.
 */
- (void)viewWillAppear:(BOOL)animated {
	[self updateNavigationBar];
	[super viewWillAppear:YES];
}

/**
 * Reset the view prior to it disappearing.
 */
- (void)viewDidDisappear:(BOOL)animated {
	[eventInfoView setZoomScale:1.0 animated:NO];
	[super viewDidDisappear:YES];
}

/**
 * Initialize the event viewer.
 */
- (id)initWithNibName:(NSString *)nibNameOrNil 
			   bundle:(NSBundle *)nibBundleOrNil {
    if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
        // Create the label content view and set its properties
		zoomableView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 
																VIEW_WIDTH, 
																VIEW_HEIGHT)];
		zoomableView.clipsToBounds = YES;
		
		// Create the scrollable event view and set its properties
		eventInfoView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 
																	   VIEW_WIDTH, 
																	   VIEW_HEIGHT)];
		eventInfoView.backgroundColor = [UIColor lightGrayColor];
		eventInfoView.contentSize = CGSizeMake(VIEW_WIDTH, VIEW_HEIGHT+50);
		eventInfoView.minimumZoomScale = MIN_ZOOM_SCALE;
		eventInfoView.maximumZoomScale = MAX_ZOOM_SCALE;
		eventInfoView.clipsToBounds = YES;
		//eventInfoView.bounces = NO;
		eventInfoView.delegate = self;
		
		// Acknowledge single finger double tap gesture support
		UITapGestureRecognizer *singleFingerDoubleTap;
		singleFingerDoubleTap = [UITapGestureRecognizer alloc];
		[singleFingerDoubleTap initWithTarget:self 
									   action:@selector(handleSingleFingerDoubleTap:)];
		singleFingerDoubleTap.numberOfTapsRequired = 2;
		[eventInfoView addGestureRecognizer:singleFingerDoubleTap];
    }
	
    return self;
}

/**
 * Deallocate the event viewer.
 */
- (void)dealloc {
	[locationButton release];
	[eventInfo release];
	[zoomableView release];
	[eventInfoView release];
	[sharedEventViewer release];
    [super dealloc];
}

@end
